package com.wayne.controller;

import com.wayne.domain.User;
import com.wayne.repository.UserRepository;
import com.wayne.util.CheckUtil;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import javax.validation.Valid;

@RestController
@RequestMapping("user")
public class UserController {
    private final UserRepository repository;

    public UserController(UserRepository repository) {
        this.repository = repository;
    }

    /**
     * 数组形式返回全部的用户
     *
     * @return
     */
    @GetMapping
    public Flux<User> getAll() {
        return repository.findAll();
    }

    /**
     * SSE 流方式返回用户数据
     *
     * @return
     */
    @GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<User> getStreamAll() {
        return repository.findAll();
    }

    /**
     * 新增用户信息
     *
     * @param user
     * @return
     */
    @PostMapping
    public Mono<User> add(@Valid @RequestBody User user) {
        //spring data jpa 里面，新增修改都是save，有id是修改，没有就是新增
        user.setId(null);
        CheckUtil.checkName(user.getName());
        return repository.save(user);
    }

    /**
     * 根据ID删除用户信息 删除成功返回200 不存在的时候返回404
     *
     * @param id
     * @return
     */
    @DeleteMapping("/{id}")
    public Mono<ResponseEntity<Void>> delete(@PathVariable("id") String id) {
        return repository.findById(id)
                .flatMap(user -> repository.delete(user)
                        .then(Mono.just(new ResponseEntity<Void>(HttpStatus.OK))))
                .defaultIfEmpty(new ResponseEntity<>(HttpStatus.NOT_FOUND));
    }

    /**
     * 修改用户，成功返回200和修改后的数据 不存在的时候返回404
     *
     * @param id
     * @param user
     * @return
     */
    @PutMapping("/{id}")
    public Mono<ResponseEntity<User>> update(@PathVariable("id") String id, @Valid @RequestBody User user) {
        CheckUtil.checkName(user.getName());
        return repository.findById(id)
                .flatMap(u -> {
                    u.setAge(user.getAge());
                    u.setName(user.getName());
                    return repository.save(u);
                })
                .map(u -> new ResponseEntity<User>(u, HttpStatus.OK))
                .defaultIfEmpty(new ResponseEntity<>(HttpStatus.NOT_FOUND));
    }

    /**
     * 根据ID查找用户 存在返回用户信息，不存在返回404
     *
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public Mono<ResponseEntity<User>> findUserById(@PathVariable("id") String id) {
        return repository.findById(id)
                .map(user -> new ResponseEntity<User>(user, HttpStatus.OK))
                .defaultIfEmpty(new ResponseEntity<>(HttpStatus.NOT_FOUND));
    }

    /**
     * 根据年龄段查找对应的用户信息 数组返回
     *
     * @param start
     * @param end
     * @return
     */
    @GetMapping("/age/{start}/{end}")
    public Flux<User> findByAge(@PathVariable("start") int start, @PathVariable("end") int end) {
        return repository.findByAgeBetween(start, end);
    }

    /**
     * 根据年龄段查找对应的用户信息 流返回
     *
     * @param start
     * @param end
     * @return
     */
    @GetMapping(value = "/stream/age/{start}/{end}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<User> streamFindByAge(@PathVariable("start") int start, @PathVariable("end") int end) {
        return repository.findByAgeBetween(start, end);
    }

    /**
     * 根据年龄段查找对应的用户信息 数组返回
     *
     * @param start
     * @param end
     * @return
     */
    @GetMapping("/old/{start}/{end}")
    public Flux<User> oldUser(@PathVariable("start") int start, @PathVariable("end") int end) {
        return repository.oldUser(start, end);
    }
}
